package org.jeecg.modules.message.task;

import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.common.util.DateUtils;
import org.jeecg.modules.bid.entity.Bid;
import org.jeecg.modules.bid.service.IBidService;
import org.jeecg.modules.message.WebSocket.WebSocketServer;
import org.jeecg.modules.message.entity.ProcurementMessage;
import org.jeecg.modules.message.service.IProcurementMessageService;
import org.jeecg.modules.purchase.entity.PurchasePlan;
import org.jeecg.modules.purchase.service.IPurchasePlanService;
import org.jeecg.modules.supplier.service.IProcUserSupplierRelationService;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 消息同步定时任务类
 * 用于定时同步消息到客户端
 */
@Component
@Slf4j
public class MessageSyncTask {

    @Resource
    private IProcurementMessageService procurementMessageService;


    @Resource
    private IPurchasePlanService purchasePlanService;

    @Resource
    private IProcUserSupplierRelationService procUserSupplierRelationService;

    @Resource
    private IBidService bidService;
    /**
     * 每30分钟同步一次未读消息
     * 0 0/30 * * * ? 表示每30分钟执行一次
     */
    @Scheduled(cron = "0 0/30 * * * ?")
    public void syncUnreadMessages() {
        try {
            log.info("【消息同步】开始执行未读消息同步任务，当前时间：{}", DateUtils.now());

            // 获取所有用户的未读消息
            List<ProcurementMessage> allUnreadMessages = procurementMessageService.list(new com.baomidou.mybatisplus.core.conditions.query.QueryWrapper<ProcurementMessage>()
                    .eq("read_status", "0") // 0表示未读
                    .orderByDesc("create_time"));

            if (allUnreadMessages.isEmpty()) {
                log.info("【消息同步】暂无未读消息需要同步");
                return;
            }

            // 按接收人分组
            Map<String, List<ProcurementMessage>> messageGroupByReceiver = allUnreadMessages.stream()
                    .collect(Collectors.groupingBy(ProcurementMessage::getReceiver));

            // 发送消息给每个用户
            for (Map.Entry<String, List<ProcurementMessage>> entry : messageGroupByReceiver.entrySet()) {
                String receiver = entry.getKey();
                List<ProcurementMessage> userMessages = entry.getValue();

                // 构建消息数据
                Map<String, Object> messageData = new java.util.HashMap<>();
                messageData.put("type", "unread_messages");
                messageData.put("count", userMessages.size());
                messageData.put("messages", userMessages);

                // 转换为JSON字符串
                String jsonMessage = JSON.toJSONString(messageData);

                // 发送消息
                boolean success = WebSocketServer.sendMessageToUser(receiver, jsonMessage);
                log.info("【消息同步】向用户: {} 同步 {} 条未读消息", receiver, userMessages.size());
            }

            log.info("【消息同步】未读消息同步任务执行完成，共同步 {} 条消息给 {} 个用户",
                    allUnreadMessages.size(), messageGroupByReceiver.size());
        } catch (Exception e) {
            log.error("【消息同步】未读消息同步任务执行失败: {}", e.getMessage(), e);
        }
    }

    /**
     * 每天凌晨1点统计消息数量
     * 0 0 1 * * ? 表示每天凌晨1点执行一次
     */
    @Scheduled(cron = "0 0 1 * * ?")
    public void statisticsMessageCount() {
        try {
            log.info("【消息统计】开始执行消息数量统计任务，当前时间：{}", DateUtils.now());

            // 这里可以实现消息数量统计逻辑
            // 例如：统计每个用户的消息总数、未读消息数等

            // 可以将统计结果存储到数据库或缓存中

            log.info("【消息统计】消息数量统计任务执行完成");
        } catch (Exception e) {
            log.error("【消息统计】消息数量统计任务执行失败: {}", e.getMessage(), e);
        }
    }

    /**
     * 投标截止提醒定时任务
     * 每天都要去对比它的截止时间，如果少于两天的话，发一次消息通知,到投标截止时间为止。
     * 0 0 1 * * ? 表示每天凌晨1点执行一次
     */
    @Scheduled(cron = "0 0 1 * * ?")
    public void beBidDeadlineReminder() {
        try {
            // 获取当前时间
            LocalDateTime now = LocalDateTime.now();
            // 获取所有招标截止时间少于两天的采购计划
            List<PurchasePlan> purchasePlanList = purchasePlanService.list(new com.baomidou.mybatisplus.core.conditions.query.QueryWrapper<PurchasePlan>()
                    .eq("status", "1")
                    .orderByDesc("create_time")
                    .lt("bidding_end_time", now.plusDays(2).minusSeconds(1))
                    .gt( "bidding_end_time", now.plusSeconds(1)));

            for (PurchasePlan purchasePlan : purchasePlanList) {
                // 根据purchasePlanId,在proc_bid表中查找对应的投标记录，如果bidStatus=1或者2，则是未投标的供应商，返回列表
                List<Bid> bidList = bidService.list(new com.baomidou.mybatisplus.core.conditions.query.QueryWrapper<Bid>()
                        .eq("purchaseId", purchasePlan.getId())
                        .in("bidStatus", Arrays.asList("1", "2"))); // 使用字符串类型匹配数据库中的String字段

                // 如果有未投标的供应商，向他们发消息提醒
                if (!bidList.isEmpty()) {
                    List<String> receiverIds = bidList.stream().map(Bid::getSupplierId).collect(Collectors.toList());
                    // 发送消息并保存进proc_message
                    procurementMessageService.sendBatchBiddingReminder(purchasePlan.getId(), purchasePlan.getProjectName(),
                            purchasePlan.getBiddingEndTime().toString(), receiverIds, "供应商");
                }
                    List<Bid> adminbidList = bidService.list(new com.baomidou.mybatisplus.core.conditions.query.QueryWrapper<Bid>()
                            .eq("purchaseId", purchasePlan.getId())
                            .in("bidStatus", Arrays.asList("4")));
                    if (adminbidList.isEmpty()) {//向管理员发送消息提醒，没有供应商投标
                        // 发送消息并保存进proc_message
                        procurementMessageService.sendBatchBiddingReminder(purchasePlan.getId(), purchasePlan.getProjectName(),
                                purchasePlan.getBiddingEndTime().toString(),procUserSupplierRelationService.getAdminSupplierList(),
                                purchasePlan.getCreateBy());
                    }
            }
            log.info("【投标即将截止提醒】开始执行投标截止提醒任务，当前时间：{}", DateUtils.now());
        } catch(Exception e){
                log.error("【投标即将截止提醒】投标截止提醒任务执行失败: {}", e.getMessage(), e);
        }

    }
    /**
     * 投标截止提醒定时任务
     * 每天都要去对比它的截止时间，如果在24小时前截止，发一次消息通知给用户
     * 0 30 1 * * ? 表示每天凌晨1点30分执行一次
     */
    @Scheduled(cron = "0 30 1 * * ?")
    public void afBidDeadlineReminder() {
        try {
            // 获取当前时间
            LocalDateTime now = LocalDateTime.now();
            // 获取所有招标截止时间少于24小时的采购计划
            List<PurchasePlan> purchasePlanList = purchasePlanService.list(new com.baomidou.mybatisplus.core.conditions.query.QueryWrapper<PurchasePlan>()
                    .eq("status", "1")
                    .orderByDesc("create_time")
                    .gt("bidding_end_time",now.minusDays(1).plusSeconds(1))
                    .lt("bidding_end_time", now.minusSeconds(1)));
            if (purchasePlanList.isEmpty()) {
                log.info("【投标已截止提醒】暂无投标截止时间在24小时前的采购计划");
                return;
            }
            for (PurchasePlan purchasePlan : purchasePlanList) {

            // 根据purchasePlanId,在proc_bid表中查找对应的投标记录，如果bidStatus=1或者2，则是未投标的供应商，返回列表
            List<Bid> bidList = bidService.list(new com.baomidou.mybatisplus.core.conditions.query.QueryWrapper<Bid>()
                    .eq("purchaseId", purchasePlan.getId())
                    .in("bidStatus", Arrays.asList("1", "2"))); // 使用字符串类型匹配数据库中的String字段

            // 如果有未投标的供应商，向他们发消息提醒
            if (!bidList.isEmpty()) {
                List<String> receiverIds = bidList.stream().map(Bid::getSupplierId).collect(Collectors.toList());
                // 发送消息并保存进proc_message
                procurementMessageService.afSendBatchBiddingReminder(purchasePlan.getId(), purchasePlan.getProjectName(),
                        purchasePlan.getBiddingEndTime().toString(), receiverIds, "供应商");
            }
                List<Bid> adminbidList = bidService.list(new com.baomidou.mybatisplus.core.conditions.query.QueryWrapper<Bid>()
                        .eq("purchaseId", purchasePlan.getId())
                        .in("bidStatus", Arrays.asList("4")));
                if (adminbidList.isEmpty()) {//向管理员发送消息提醒，没有供应商投标
                    // 发送消息并保存进proc_message
                    procurementMessageService.afSendBatchBiddingReminder(purchasePlan.getId(), purchasePlan.getProjectName(),
                            purchasePlan.getBiddingEndTime().toString(),procUserSupplierRelationService.getAdminSupplierList(),
                            purchasePlan.getCreateBy());
                }
            }
        }
        catch (Exception e) {
            log.error("【投标已截止提醒】投标截止提醒任务执行失败: {}", e.getMessage(), e);
        }
    }

}
